package com.yh.eval;

import android.Manifest;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.PackageManager;
import android.location.Location;
import android.location.LocationManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.TextView;
import android.widget.Toast;

import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;

import com.yh.service.GPSService;
import com.yh.util.AmapLocationUtils;
import com.yh.util.Config;
import com.yh.util.NetWorkUtils;
import com.yh.util.ShellUtils;
import com.yh.util.WebViewUtil;

import java.io.File;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/**
 * 4Gw网络、GSP信号和TFCard功能验证
 */
public class TF4GActivity extends AppCompatActivity {

    private final String TAG = getClass().getSimpleName();
    private CarBusModel mBusModel;
    private TextView mTv4G;
    private TextView mTvGPS;
    private TextView mTvLocation;
    WebView mWebView;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        WebViewUtil.hookWebView();
        setContentView(R.layout.activity_tf4g);
        mWebView = findViewById(R.id.webView);
        mTv4G = findViewById(R.id.tv_4gStatus);
        mTvGPS = findViewById(R.id.tv_gpsStatus);
        mTvLocation = findViewById(R.id.tv_amapLocation);
        setTitle(getTitle() + " sysVersion: " + ShellUtils.execShellCmd("getprop firmwareVersion") +
                " ("+ ShellUtils.execShellCmd("getprop ro.build.date") +")") ;
        /*

         java.lang.UnsatisfiedLinkError: dlopen failed: "/data/app/com.ilin.atelec-Gf114UgRWTQnJiHC7-pP2g==/lib/arm/libserial_port.so" has bad ELF magic
            at java.lang.Runtime.loadLibrary0(Runtime.java:1016)
            at java.lang.System.loadLibrary(System.java:1657)
            at android_serialport_api.SerialPort.<clinit>(SerialPort.java:84)
            at com.serial.opt.UartCommunication.<init>(UartCommunication.java:72)
            at com.serial.opt.UartCommunication.getInstance(UartCommunication.java:90)
            at com.serial.opt.UartWorkerCH.<init>(UartWorkerCH.java:133)
            at com.car.eval.CarBusModel.init(CarBusModel.java:74)
            at com.car.eval.TF4GActivity.openCH4G(TF4GActivity.java:90)
            at com.car.eval.TF4GActivity.onCreate(TF4GActivity.java:69)
            at android.app.Activity.performCreate(Activity.java:7042)
            at android.app.Activity.performCreate(Activity.java:7033)
            at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1214)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2731)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2856)
            at android.app.ActivityThread.-wrap11(Unknown Source:0)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1589)
            at android.os.Handler.dispatchMessage(Handler.java:106)
            at android.os.Looper.loop(Looper.java:164)
            at android.app.ActivityThread.main(ActivityThread.java:6494)
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:438)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:807)
---------------------------- PROCESS ENDED (4764) for package com.ilin.atelec ----------------------------
         */
        openCH4G();
        initGpsTest();
//        WifiSetupUtil.setWifiAccountPassword(this, "华秋电子", "HQdz*2023*");
        register();
        testGps();
        startAMapLocation();
    }

    private void startAMapLocation() {
        AmapLocationUtils.getInstance().setLocationListener(aMapLocation -> {
            String info = AmapLocationUtils.getInstance().getInfo(aMapLocation, false);
            mTvLocation.setText(info);
        });
        AmapLocationUtils.getInstance().startLocation();
    }

    private void openCH4G(){
        try {
            if (null == mBusModel) {
                mBusModel = CarBusModel.getInstance(this);
            }
            mBusModel.init(Config.SERIAL_CH0, Config.BATE);
        } catch (Exception e) {
            e.printStackTrace();
        }

        String usbDevices = ShellUtils.execShellCmd("lsusb");
//        mTv4G.setText(usbDevices);
        //  Bus 001 Device 004: ID 1286:4e3c
        //  能获取到1286:4e3c 就表示启动成功 (VID:PID)
        boolean cat4StartSuccess = usbDevices.toLowerCase().contains("4e3c");
//        Toast.makeText(this,cat4StartSuccess ? "4G模块启动成功" : "4G模块未启动", Toast.LENGTH_LONG).show();
        mTv4G.setText(cat4StartSuccess ? "模块已启动成功" : "4g模块未能启动，请排查硬件问题！");
        if (!cat4StartSuccess){
            mTv4G.setTextColor(getResources().getColor(R.color.colorAccent));
        }
    }

    private void initGpsTest() {
       findViewById(R.id.btn_testGps).setOnClickListener(v->{
           try {
//               Intent it = new Intent();// 打开GPS测试app
//               it.setComponent(new ComponentName("com.android.gpstest", "com.android.gpstest.GpsTestActivity"));
//               startActivity(it);
               ShellUtils.execShellCmd("setprop persist.boot.noril2 true"); // 重启gps服务
               Toast.makeText(this, "重启gps服务", 1).show();
           } catch (Exception e) {
               e.printStackTrace();
               Toast.makeText(this, e.getMessage(), 1).show();
           }
       });
        findViewById(R.id.btn_testGps2).setOnClickListener(v->{
            try {
                Intent it = new Intent();
                // 打开GPS测试app
//               com.chartcross.gpstestplus/.GPSTestPlus  芯片厂的
                it.setComponent(new ComponentName("com.chartcross.gpstestplus", "com.chartcross.gpstestplus.GPSTestPlus"));
                startActivity(it);
            } catch (Exception e) {
                e.printStackTrace();
                Toast.makeText(this, e.getMessage(), 1).show();
            }
        });
        findViewById(R.id.btn_getLoc).setOnClickListener(v->{
            getGpsLocation();
        });
    }

    private void setGpsLS() {
       GPSService.setLs(rs -> {
           mTvGPS.setText(rs);
       });
    }

    public void onClick(View v){
        if (v.getId() == R.id.btnBack) finish();
        if (v.getId() == R.id.btn_web){
            openBaidu();
        }
//        if (v.getId() == R.id.btn_testApi){
//            new Thread(()->{
//                HttpUtil.getDataAsync(rs-> {
//                    mWebView.post(()->{
//                        Toast.makeText(TF4GActivity.this, "httpRS = " + rs , 1).show();
//                    });
//                });
//            }).start();
//        }
        if (v.getId() == R.id.btn_goBrowse){
            if (mWebView.canGoBack()) mWebView.goBack();
        }
        if (v.getId() == R.id.btn_has4G){
            mBusModel.checkHas4G(data -> {
                boolean has4GModel = data.contains("OK");
                Log.i(TAG, "checkHas4G: 是否有扩展4G模块 = " + has4GModel);
                if (!has4GModel) set4gStatus("没硬件模块");
            });
        }
        if (v.getId() == R.id.btn_checkInsert){
            mBusModel.checkInsertCard(data -> {
                boolean isInsert = data.contains("READY");
                // +CPIN: READY //SIM 卡已准备好
                System.out.println("Gps4GActivity.onClick 是否插入4G卡 = " + isInsert);
                if (isInsert) checkCsqAndSysInfo();
                else set4gStatus("未插卡");
            });
        }
        if (v.getId() == R.id.btn_connect){
//            atConnect();
//            Toast.makeText(this, "GPS "+ (isGpsEnabled(this) ? "可用":"不可用"), 1 ).show();
            mBusModel.switchGps(data -> {
                System.out.println("TF4GActivity.onClick openGPS rs= " + data);
                mTvGPS.post(()->{
                    Toast.makeText(this, "GPS打开 "+ (data.contains("OK") ? "成功":"失败"), 0 ).show();
                });
            }, true);
        } else if (v.getId() == R.id.btn_createSocket) { // ping
            createSocket();
        }
        if (v.getId() == R.id.btn_send){
//            sendData();
//            mBusModel.hotSwapEnable(data -> {
//                System.out.println("TF4GActivity enable hotSwap rs = " + data);
//                setTestRs("enable hotSwap =" + data);
//            });
            mBusModel.switchGps(data -> {
                System.out.println("TF4GActivity.onClick openGPS rs= " + data);
                mTvGPS.post(()->{
                    Toast.makeText(this, "GPS关闭 "+ (data.contains("OK") ? "成功":"失败"), 0 ).show();
                });
            }, false);
        } else if (v.getId() == R.id.btn_closeAll) {
//            closeAll();
            mBusModel.hotSwapCheck(data -> {
                System.out.println("TF4GActivity.check hotSwap rs = " + data);
                setTestRs("check hotSwap =" + data);
            });
        }else if (v.getId() == R.id.btn_disHot){
            mBusModel.hotSwapDisable(data -> {
                setTestRs("dis hotSwap =" + data);
            });
        }
        if (System.currentTimeMillis() - lastClickTime < 1000){
            System.err.println("TF4GActivity.onClick 重复点击了");
            return;
        }
        if (v.getId() == R.id.btn_write){
            new Thread(()->{
                testSaveFile();
            }).start();
        } else if (v.getId() == R.id.btn_read){
            readWriteFiles();
        } else if (v.getId() == R.id.btn_file){
            cleanFiles();
        }
    }

    private void readWriteFiles() {
        if (mWriteRootPath == null) return;
        File file = new File(mWriteRootPath);
        if (!file.exists()) return;
        TextView tvFiles = findViewById(R.id.tv_files);
        tvFiles.setText("");
        int count = 0;
        for (File fl: file.listFiles()){
            if (fl.isFile() && fl.getName().endsWith(fileType)){
                tvFiles.append(fl.getAbsolutePath() + "\n");
                count ++;
            }
        }
        if (count == 0){
            tvFiles.setText(String.format("没有写入的%s文件", fileType == null ? "" : fileType));
        }

        File txtFile = new File(mWriteRootPath + "/data.txt");
        if (txtFile.exists()){
            tvFiles.append("data.txt 文件内容如下 \n");
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                try {
                    String fileContent = new String(Files.readAllBytes(Paths.get(txtFile.getAbsolutePath())));
                    tvFiles.append(fileContent);
                } catch (IOException e) {
                    throw new RuntimeException(e);
                }
            }
        }
    }

    private void cleanFiles() {
        if (mWriteRootPath == null) return;
        File file = new File(mWriteRootPath);
        if (!file.exists()) return;
        for (File fl : file.listFiles()) {
            if (fl.isFile() && fl.getName().endsWith(fileType)) {
                fl.delete();
            }
        }
        File txtFile = new File(mWriteRootPath + "/data.txt");
        txtFile.delete();
        Toast.makeText(this, "已清除写入文件", 0).show();
        readWriteFiles();
    }

    long lastClickTime;

    void setTestRs(String data){
        mTvGPS.post(() -> {
            mTvGPS.setText(data);
        });
    }

    private void openBaidu() {
        if (mWebView == null) return;
        mWebView.setVisibility(View.VISIBLE);
//        mWebView.loadUrl("http://163.177.151.110/");
        mWebView.loadUrl("https://music.163.com/");
        WebViewUtil.setWebView(this, mWebView);
        mWebView.setWebViewClient(new WebViewClient(){
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                //使用WebView加载显示url
                view.loadUrl(url);
                return true;
            }
        });
        WebViewUtil.setInnerLinkEnable(mWebView);
//        new Thread(HttpUtil::getDataAsync).start();
    }

    private void atConnect() {
        mBusModel.setAPN(data -> {
            Log.i(TAG, "atConnect: setApn = " + data);
            mBusModel.restRspLs();
            mBusModel.actionQIP(data1 -> {
                Log.i(TAG, "atConnect: actionQip = " + data1);

            });
        });

    }

    Thread thread;
    private void createSocket(){
//        mBusModel.crateSocket(data -> {
//            Log.i(TAG, "create: = " + data);
//
//        });
        if (thread != null && thread.isAlive()) return;
        thread = new Thread(()->{
            int i = 0;
            String rs = "ping ";
            int state = -1;
            while (i < 5){
                state = NetWorkUtils.isNetPingUsable();
                System.out.println("TF4GActivity.ping State = " + state);
                if (state == 0) break;
                i++;
            }
            if (state == 0) rs += "网络可用";
            else if (state == 1) rs += "未认证";
            else if (state == 2) rs += "无网络";
            String finalRs = rs;
            mWebView.post(()->{
                Toast.makeText(this, finalRs, 1).show();
            });
        });
        thread.start();
    }

    void sendData(){
//        mBusModel.hasSocket(data -> {
//            Log.i(TAG, "sendData: socketConnect = " + data);
//           boolean hasConnect = data.contains("OK");
//           mBusModel.restRspLs();
//           if (hasConnect){
               mBusModel.sendData(data1 -> {
                   System.out.println("Gps4GActivity.sendData rsp = " + data1);

               }, null, 1);
//           }else {
//               Log.e(TAG, "sendData: socket未连接 ！" );
//           }
//        });

    }

    void closeAll(){
        mBusModel.closeSocket();
//        mBusModel.closeTcpIp();
    }

    void checkCsqAndSysInfo(){
        mBusModel.checkCSQ(data -> { // 信号
            //  +CSQ: 13,99
            System.out.println("Gps4GActivity.checkCsq = " + data);
            mBusModel.restRspLs();
            String csq = data.substring(data.indexOf("Q:") + 3, data.indexOf(","));
            setCsqLevel(csq);
            mBusModel.checkSysInfo(data1 -> { // 注册信息
                System.out.println("Gps4GActivity.checkSysInfo = " + data);
                mBusModel.restRspLs();
            });
        });
    }

    private void setCsqLevel(String csq) {
        int level = Integer.parseInt(csq.trim());
        String levStr = "";
        // 0-31之间 ，至少大于10
        if (level > 28){
            levStr = "信号强";
        }else if (level > 18){
            levStr = "信号中";
        }else if (level > 10){
            levStr = "信号弱";
        }else {
            levStr = "没信号";
        }
        set4gStatus(levStr);
//        if (level > 10) testGps();
    }

    private void testGps() {
        setGpsLS();
        Intent it = new Intent(getApplicationContext(), GPSService.class);
        it.setAction("act.init.gps");
        startService(it);
    }

    private void set4gStatus(String status){
        String finalLevStr = status;
        mTv4G.post(()->{
            mTv4G.setText(finalLevStr);
        });
    }

    String mWriteRootPath = Environment.getExternalStorageDirectory().getPath();
    String fileType = "json";
    void testSaveFile(){
        String state = Environment.getExternalStorageState();
        if (Environment.MEDIA_MOUNTED.equals(state)) {
            // 外部存储可以读取和写入
            System.out.println("TF4GActivity.testSaveFile 外部存储可以读取和写入");
        } else if (Environment.MEDIA_MOUNTED_READ_ONLY.equals(state)) {
            // 外部存储只读
            System.out.println("TF4GActivity.testSaveFile 外部存储只读");
        } else {
            // 外部存储不可用
            System.err.println("TF4GActivity.testSaveFile 外部存储不可用");
        }
//        String rootPath = getFilesDir().getPath();
        String rootPath = mWriteRootPath;
        System.out.println("TF4GActivity.testSaveFile " + rootPath);
        fileType = "json";
        File txtFile = new File(rootPath + "/data.txt");
        String fileName = String.format("data%s.json", System.currentTimeMillis()/1000);
        File file = new File(rootPath + "/" + fileName);
        // 要写入的字符串
        String jsonString = "{\"name\": \"John\", \"age\": 32}";

        try {
            // 追加的文本
            String textToAppend = fileName + "\t";
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                if (!txtFile.exists()){
                    txtFile.createNewFile();
                }
                Files.write(Paths.get(txtFile.getAbsolutePath()), textToAppend.getBytes(), StandardOpenOption.APPEND);
            }

            FileOutputStream fos = null;
            fos = new FileOutputStream(file);
            //将buf中的数据写入fos
            fos.write(jsonString.getBytes());
            //将fos的数据保存到内核缓冲区
            //不能确保数据保存到物理存储设备上，如突然断点可能导致文件未保存
            fos.flush();
            //将数据同步到达物理存储设备
            FileDescriptor fd = fos.getFD();
            fd.sync();
            System.out.println("数据已写入磁盘，文件: " + file.getAbsolutePath());
            runOnUiThread(()->{
                Toast.makeText(getBaseContext(), "写入成功:"+file.getName(), 1).show();
            });
        } catch (IOException e) {
            e.printStackTrace();
            runOnUiThread(()->{
                Toast.makeText(getBaseContext(), e.getMessage(), 1).show();
            });
        }
    }

    public boolean isGpsEnabled(Context context) {
        LocationManager locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
        return locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
    }

    // 声明TF卡监听广播
    BroadcastReceiver mountReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            Uri data = intent.getData();
            String path = data.getPath();
            File file = new File(path);
            System.out.println(".onReceive 插拔SdCard = " + action);
            System.out.println(".onReceive 插拔SdCard = " + path);
            TextView tv = findViewById(R.id.tv_tfCard);
            if (Intent.ACTION_MEDIA_MOUNTED.equals(action)){
                tv.setText("插入：" + path);
            }else {
                tv.setText("拔出：" +path);
            }
            // doing
        }
    };

    // 注册接受广播
    void register() {
        try {
            IntentFilter intentFilter = new IntentFilter();
            intentFilter.addAction(Intent.ACTION_MEDIA_MOUNTED);
            intentFilter.addAction(Intent.ACTION_MEDIA_UNMOUNTED);
            intentFilter.setPriority(1000);
            intentFilter.addDataScheme("file");
            registerReceiver(mountReceiver, intentFilter);
        } catch (Exception e) {
            e.printStackTrace();
        }

        findViewById(R.id.tv_tfCard).setOnClickListener(v -> {
            // 启用wifi adb 调试并打印显示ip地址
            ShellUtils.execShellCmd("setprop persist.internet.adb.enable 1");
            String result = ShellUtils.execShellCmd("ifconfig");
            ((TextView)v).setText(result);
        });
        findViewById(R.id.tv_tfCard).setOnLongClickListener(v -> {
            try { // 长按进入loader模式
                //    Runtime.getRuntime().exec("su -c 'reboot bootloader'"); // 不能bootloader
//                    Process process = Runtime.getRuntime().exec("su"); // 也不行
                Runtime.getRuntime().exec("reboot loader");
                //       ShellUtils.execShellCmd("reboot loader");
            } catch (IOException e) {
                e.printStackTrace();
            }
            return false;
        });
    }

    // 注销
    void unregister() {
        try {
            unregisterReceiver(mountReceiver);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (mBusModel != null) mBusModel.stop();
        unregister();
        AmapLocationUtils.getInstance().stopLocation();
    }

    void getGpsLocation(){
        //获取位置信息的入口级类，要获取位置信息，首先需要获取一个LocationManger对象
        LocationManager lm = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Toast.makeText(this,"请手机GPS定位服务！",Toast.LENGTH_LONG).show();
            return;
        }

        if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
                != PackageManager.PERMISSION_GRANTED){
            Toast.makeText(this,"请授予位置信息权限！",Toast.LENGTH_LONG).show();
            return;
        }

         Location location = lm.getLastKnownLocation(LocationManager.GPS_PROVIDER);

        if (location ==null) {
            Toast.makeText(this,"获取位置失败！",Toast.LENGTH_LONG).show();
            return;
        }

        double latitude = location.getLatitude();
        double longitude = location.getLongitude();

        mTvGPS.setText("纬度：" + latitude +"\n" +"经度：" + longitude);

    }

}
